<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>this的指向问题</title>
</head>

<body>

</body>

</html>

<script>
    // 1.在全局环境当中
    let fun1 = function () {
        console.log('全局环境当中的 this 的指向：', this)
    }

    fun1()

    // 2.对象当中使用的方法
    let obj = {
        fun: function() {
            console.log('对象当中的方法:', this)
        }
    }
    obj.fun()
    
    // 3.当找不到函数的调用者的时候，this指向的是 window
    let obj2 = {
        fun2: function() {
            setTimeout(function() {
                console.log('回调函数中的this:', this)
            })
        },
        fun3: function() {
            setTimeout(() => {
                console.log('回调函数是箭头函数：', this)
            })
        }
    }
    obj2.fun2()
    obj2.fun3()

    // 4.通过存储变量的方式解决 this 问题
    let obj3 = {
        fun4: function(){
            let $this = this
            setTimeout(function() {
                console.log('保存在变量中的this：', $this)
            })
        }
    }

    obj3.fun4()

    // 5.通过改变方法的绑定对象来固定 this
    var value1 = 200
    class CreateObj {
        constructor() {
            this.value1 = 100
        }

        fun5() {
            console.log('class类中的this',this)
        }
    }

    function fun6() {
        console.log('fun6中的this',this)
    }


    let theObj1 = new CreateObj()
    // theObj1.fun5()
    var tempFun5 = theObj1.fun5
    this.tempFun5() // 若直接用 tempFun5() 调用函数，返回的 this 是 undefined 因为没有给方法指定调用对象

    // 6.通过 函数中的 bind 来更改绑定
    class MyClass {
        constructor() {
            this.value = 100
            // this.getValue.bind(this)
        }
        getValue() {
            return this.value
        }
    }

    let class1 = new MyClass()

    // 7.也可以通过 call 和 apply 来进行一次性的调用

    // 8.不过现在比较常用的还是通过回调函数觉得方式来解决
</script>